home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 501-525 / disk_512 / csh / csh515s.lzh / comm1.c < prev    next >
C/C++ Source or Header  |  1991-06-23  |  35KB  |  1,533 lines

  1. /*
  2.  * COMM1.C
  3.  *
  4.  * Matthew Dillon, August 1986
  5.  *
  6.  * Version 2.07M by Steve Drew 10-Sep-87
  7.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  8.  * Version 5.00L by Urban Mueller 17-Feb-91
  9.  *
  10.  */
  11.  
  12. #include "shell.h"
  13.  
  14. /* comm1.c */
  15. static void display_file(char *filestr);
  16. static int search_file(char *s);
  17. static int quicksearch(char *name, int nocasedep, char *pattern);
  18. static int rm_file(char *file);
  19. static void setsystemtime(struct DateStamp *ds);
  20. static int found( char *lstart, int lnum, int loffs, char *name, char left );
  21. static void recurse(char *name, int (*action)(char *));
  22. static void recurse2( char *name, void (*action)(FIB *));
  23. static void lformat( char *s, char *d, struct file_info *info );
  24.  
  25. extern int has_wild;
  26.  
  27. int
  28. do_sleep( void )
  29. {
  30.     int i;
  31.  
  32.     if (ac == 2) for (i=atoi(av[1]); i>0 && !CHECKBREAK(); i--) Delay(50);
  33.     return 0;
  34. }
  35.  
  36. int
  37. do_protect( void )
  38. {
  39.     static char flags[]="DEWRAPSH";
  40.     char *s, *p;
  41.     long setmask=0, clrmask=0xFF, mask;
  42.     int  i, mode=0, stat;
  43.     struct DPTR *dp;
  44.  
  45.     for (s=strupr(av[--ac]); *s; s++) {
  46.         if (*s=='=') { mode=0; continue; }
  47.         if (*s=='+') { mode=1; clrmask=FIBF_ARCHIVE; continue; }
  48.         if (*s=='-') { mode=2; clrmask=FIBF_ARCHIVE; continue; }
  49.  
  50.         if (p=index(flags, *s)) {
  51.             if( mode==0 ) setmask|= 1<<(p-flags), clrmask=0xFF;
  52.             if( mode==1 ) setmask|= 1<<(p-flags);
  53.             if( mode==2 ) clrmask|= 1<<(p-flags);
  54.         } else
  55.             ierror(av[ac],500);
  56.     }
  57.  
  58.     for (i=1; i<ac; i++) {
  59.         if( (dp=dopen(av[i],&stat))) {
  60.             mask = dp->fib->fib_Protection ^ 0x0F;
  61.             mask&=~clrmask;
  62.             mask|= setmask;
  63.             dclose(dp);
  64.             if( !SetProtection( av[i], mask ^ 0x0F))
  65.                 pError(av[i]);
  66.         } else
  67.             pError(av[i]);
  68.     }
  69.     return 0;
  70. }
  71.  
  72. int
  73. do_filenote( void )
  74. {
  75.     struct DPTR *dp;
  76.     char *note;
  77.     int i, stat;
  78.  
  79.     if( options&1 ) {
  80.         for( i=1; i<ac && !dobreak(); i++ )
  81.             if( dp=dopen( av[i], &stat )) {
  82.                 printf( "%-12s %s\n", av[i],dp->fib->fib_Comment );
  83.                 dclose( dp );
  84.             }
  85.     } else {
  86.         note=av[--ac];
  87.         for (i=1; i<ac; i++) if (!SetComment(av[i], note)) pError(av[i]);
  88.     }
  89.     return 0;
  90. }
  91.  
  92. int
  93. do_cat( void )
  94. {
  95.     FILE *fi;
  96.     int lctr, i, docr=0;
  97.     char buf[256], *l;
  98.  
  99.     prepscroll(0);
  100.     if (ac<=1) {
  101.         if (has_wild) { printf("No files matching\n"); return 20; }
  102.         lctr=0;
  103.         while (fgets(buf,256,stdin) && !dobreak()) {
  104.             if (options) printf("%4d ",++lctr);
  105.             quickscroll();
  106.             l=buf+strlen( buf )-1; docr=1;
  107.             if( l>=buf && *l=='\n' ) docr=0;
  108.             fputs(buf,stdout);
  109.         }
  110.     } else {
  111.         for (i=1; i<ac; i++)
  112.             if (fi = fopen (av[i], "r")) {
  113.                 lctr=0;
  114.                 while (fgets(buf,256,fi) && !dobreak()) {
  115.                     if (options&1) printf("%4d ",++lctr);
  116.                     quickscroll();
  117.                     l=buf+strlen( buf )-1; docr=1;
  118.                     if( l>=buf && *l=='\n' ) docr=0;
  119.                     fputs(buf,stdout); fflush(stdout);
  120.                 }
  121.                 fclose (fi);
  122.             } else
  123.                 pError(av[i]);
  124.     }
  125.     if( docr && isconsole(Output()))
  126.         putchar('\n');
  127.     return 0;
  128. }
  129.  
  130.  
  131. void
  132. get_drives(char *buf)
  133. {
  134.     struct DirectoryEntry *de_head=NULL, *de;
  135.  
  136.     buf[0]=0;
  137.     AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  138.     for(de=de_head; de; de=de->de_Next) {
  139.         if( buf[0] )
  140.             strcat( buf, "\240" );
  141.         strcat( buf, de->de_Name );
  142.     }
  143.     FreeDAList(de_head);
  144. }
  145.  
  146. static char infobuf[100];
  147. static char namebuf[12];
  148.  
  149. char *
  150. drive_name( char *name )
  151. {
  152.     struct DirectoryEntry *de_head=NULL, *de;
  153.     struct MsgPort *proc=DeviceProc( name );
  154.  
  155.     strcpy( namebuf, name );
  156.     AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  157.     for(de=de_head; de; de=de->de_Next)
  158.         if( DeviceProc( de->de_Name) == proc )
  159.             strcpy( namebuf, de->de_Name );
  160.     FreeDAList(de_head);
  161.  
  162.     return namebuf;
  163. }
  164.  
  165. int
  166. do_info( void )
  167. {
  168.     struct DirectoryEntry *de_head=NULL, *de;
  169.     int i;
  170.  
  171.     puts("Unit    Size  Bytes  Used Blk/Byt-Free Full Errs  Status    Name");
  172.  
  173.     if( ac==1 ) {
  174.         AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  175.         for(de=de_head; de; de=de->de_Next)
  176.             oneinfo( de->de_Name, 0);
  177.         FreeDAList(de_head);
  178.     } else {
  179.         for( i=1; i<ac; i++ )
  180.             oneinfo( drive_name( av[i] ), 0 );
  181.     }
  182.  
  183.     return 0;
  184. }
  185.  
  186. char *
  187. oneinfo( char *name, int mode )
  188. {
  189.     BPTR lock;
  190.     struct InfoData *info;
  191.     long size, free, freebl, blocks;
  192.     char *p, buf[130], *state="          ";
  193.     char *fmt="%s\240%s\240%d\240%d\240%d\240%s\240%d%%\240%d\240%s\240%s";
  194.  
  195.     Myprocess->pr_WindowPtr = (APTR)(-1);
  196.  
  197.     infobuf[0]=0;
  198.     if( !name ) name="";
  199.     strcpy(infobuf,"0");
  200.     info=(struct InfoData *)SAllocMem(sizeof(struct InfoData),MEMF_PUBLIC);
  201.     if (lock=Lock(name,ACCESS_READ)) {
  202.         if (Info(lock, info)) {
  203.             PathName(lock, buf, 128L);
  204.             if (p=index(buf,':')) *p = '\0';
  205.             size  = ((info->id_NumBlocks + 2)* info->id_BytesPerBlock);
  206.             freebl= (info->id_NumBlocks-info->id_NumBlocksUsed);
  207.             free  = freebl * info->id_BytesPerBlock;
  208.             switch(info->id_DiskState) {
  209.                 case ID_WRITE_PROTECTED: state="Read Only "; break;
  210.                 case ID_VALIDATED:       state="Read/Write"; break;
  211.                 case ID_VALIDATING:      state="Validating"; break;
  212.             }
  213.             blocks=info->id_NumBlocks;
  214.             if( mode==0 ) fmt="%-7s%5s%6d%7d%7d %5s%4d%%%4d  %s %s\n";
  215.             sprintf(infobuf,fmt,
  216.                 name,
  217.                 itok( size ),
  218.                 info->id_BytesPerBlock,
  219.                 info->id_NumBlocksUsed,
  220.                 freebl,
  221.                 itok( free ),
  222.                 (blocks) ? (info->id_NumBlocksUsed * 100)/blocks : 0,
  223.                 info->id_NumSoftErrors,
  224.                 state,
  225.                 buf);
  226.             if( mode==2 ) sprintf( infobuf, "%d", free );
  227.             if( mode==3 ) sprintf( infobuf, "%d", freebl );
  228.             if( mode==4 ) sprintf( infobuf, "%s", itok( free ));
  229.             if( mode==5 ) sprintf( infobuf, "%s:",buf );
  230.         } else
  231.             pError (name);
  232.         UnLock(lock);
  233.     } else {
  234.         if     ( mode==1 ) sprintf( infobuf, "%s\240No disk present", name );
  235.         else if( mode==0 ) sprintf( infobuf, "%-7s No disk present\n",name);
  236.         else if( mode==5 ) sprintf( infobuf, ""  );
  237.         else               sprintf( infobuf, "0" );
  238.     }
  239.     if( mode==0 ) printf( "%s",infobuf);
  240.     FreeMem(info,sizeof(struct InfoData));
  241.  
  242.     Myprocess->pr_WindowPtr = (APTR) o_noreq;
  243.  
  244.     return infobuf;
  245. }
  246.  
  247.  
  248. /* things shared with display_file */
  249.  
  250. #define DIR_SHORT 0x1
  251. #define DIR_FILES 0x2
  252. #define DIR_DIRS  0x4
  253. #define DIR_NOCOL 0x8
  254. #define DIR_NAMES 0x10
  255. #define DIR_HIDE  0x20
  256. #define DIR_LEN   0x40
  257. #define DIR_TIME  0x80
  258. #define DIR_BACK  0x100
  259. #define DIR_UNIQ  0x200
  260. #define DIR_IDENT 0x400
  261. #define DIR_CLASS 0x800
  262. #define DIR_QUIET 0x1000
  263. #define DIR_AGE   0x2000
  264. #define DIR_VIEW  0x4000
  265. #define DIR_NOTE  0x8000
  266. #define DIR_PATH  0x10000
  267. #define DIR_LFORM 0x20000
  268. #define DIR_BOT   0x40000
  269. #define DIR_TOP   0x80000
  270.  
  271. static BPTR lastlock;
  272. static int filecount, dircount, col, colw, wwidth;
  273. static long bytes, blocks;
  274.  
  275. /* the args passed to do_dir will never be expanded */
  276.  
  277. extern expand_err;
  278. extern int w_width;
  279.  
  280. static struct DateStamp Stamp;
  281. static char *LineBuf, *LinePos, LastWasDir, *LFormat, _LFormat[80], NoTitles;
  282.  
  283. int
  284. do_dir( void )
  285. {
  286.     int i=1, c, eac, reverse, nump=ac, retcode=0;
  287.     char **eav=NULL, **av1=NULL, **av2=NULL, inter=isconsole(Output());
  288.     char linebuf[200];
  289.     int (*func)(), ac1, ac2, factor=0;
  290.  
  291.     LineBuf=LinePos=linebuf;
  292.     LastWasDir=NoTitles=0;
  293.     colw=-1;
  294.  
  295.     LFormat=_LFormat;
  296.  
  297.     if( options&DIR_CLASS ) options|=DIR_IDENT;
  298.     if( !(options & (DIR_FILES | DIR_DIRS))) options|= DIR_FILES | DIR_DIRS;
  299.  
  300.     DateStamp( &Stamp );
  301.  
  302.     col = filecount = dircount = bytes = blocks = 0L;
  303.     lastlock=0;
  304.  
  305.     wwidth=77;
  306.     if( inter ) 
  307.         wwidth=w_width;
  308.  
  309.     if( options&DIR_SHORT )
  310.         strcpy(LFormat," %-18n%19m");
  311.     else if( options&DIR_PATH )
  312.         strcpy(LFormat," %-50p %7s %d"), NoTitles=1;
  313.     else {
  314.         if( options&DIR_NOTE )
  315.             strcpy(LFormat,"   %-24n %o");
  316.         else {
  317.             strcpy(LFormat,"   %-24n %c%f ");
  318.             if( options&DIR_VIEW )
  319.                 strcat(LFormat,"%10v ");
  320.             else 
  321.                 strcat(LFormat,"%7s ");
  322.             if( !(options&DIR_QUIET) )
  323.                 strcat(LFormat,options&DIR_VIEW?"%5b ":"%4b ");
  324.             if( options&DIR_IDENT )
  325.                 strcat(LFormat,"%k");
  326.             else if( options&DIR_AGE )
  327.                 strcat(LFormat,"%a");
  328.             else 
  329.                 strcat(LFormat,"%d %t");
  330.         }
  331.     }
  332.  
  333.     if( options&DIR_LFORM )
  334.         if( ac>1 )
  335.             LFormat=av[i++];
  336.         else { 
  337.             show_usage(NULL);
  338.             return 20;
  339.         }
  340.  
  341.     if( ac == i) ++nump, av[i]="";
  342.     if( options&DIR_UNIQ) {
  343.         if( ac-i!=2 )  { show_usage(NULL); return 20; }
  344.         i=0, nump=3;
  345.     }
  346.  
  347.     prepscroll(0);
  348.     for( ; i<nump && !CHECKBREAK(); ++i ) {
  349.         if( options&DIR_UNIQ ) {
  350.             switch( i ) {
  351.                 case 0: av1=expand( av[ac-2], &ac1 );
  352.                         av2=expand( av[ac-1], &ac2 );
  353.                         eav=without( av1, ac1, av2, ac2, &eac, 1 );
  354.                         break;
  355.                 case 1: printf("\nCommon files\n");
  356.                         eav=and( av1, ac1, av2, ac2, &eac, 1 );
  357.                         break;
  358.                 case 2: printf("\n");
  359.                         eav=without( av2, ac2, av1, ac1, &eac, 1 );
  360.                         break;
  361.             }
  362.             col = filecount = dircount = bytes = blocks = 0L;
  363.             if (lastlock) UnLock(lastlock), lastlock=0;
  364.         } else if (!(eav = expand(av[i], &eac)) && IoError) {
  365.             ierror(av[i],IoError);
  366.             retcode=5;
  367.             continue;
  368.         }
  369.  
  370.         reverse= ( options&DIR_BACK ) ? 1 : 0;
  371.         func=cmp;
  372.         if( options & DIR_TIME) func=datecmp;
  373.         if( options & DIR_LEN ) func=sizecmp;
  374.         if( options & DIR_CLASS)func=classcmp;
  375.         if( options & DIR_BOT ) factor=-99999999;
  376.         if( options & DIR_TOP ) factor= 99999999;
  377.         DirQuickSort(eav, eac, func, reverse, factor);
  378.         for(c=0; c<eac && !CHECKBREAK(); ++c) {
  379.             if( options & DIR_HIDE ) {
  380.                 char *b=BaseName(eav[c]);
  381.                 int  l=strlen(b)-5;
  382.                 struct file_info *info =
  383.                     (struct file_info *)(eav[c]-sizeof(struct file_info));
  384.                 if(*b=='.'|| (l>=0 && !strcmp(b+l,".info"))||(info->flags&128))
  385.                     continue;
  386.             }
  387.             if (options & DIR_NAMES) {
  388.                 if(options&(((FILEINFO *)eav[c])->size<0? DIR_DIRS: DIR_FILES))
  389.                     puts(eav[c]);
  390.             } else
  391.                 display_file(eav[c]);
  392.         }
  393.  
  394.         if (col) { quickscroll(); printf("%s\n",LinePos=LineBuf); col=0; }
  395.  
  396.         if( LastWasDir )
  397.             printf(o_lolite), LastWasDir=0;
  398.  
  399.         if (options&DIR_UNIQ || (filecount>1 && i==nump-1)) {
  400.             blocks += filecount-dircount; /* account for dir blocks */
  401.             quickscroll();
  402.             printf(" %ld Blocks, %s Bytes used in %d files\n",
  403.                 blocks, itoa(bytes), filecount);
  404.         }
  405.         if( options&DIR_UNIQ )
  406.             free(eav);
  407.         else 
  408.             free_expand (eav);
  409.     }
  410.     if (lastlock) UnLock(lastlock), lastlock=0;
  411.  
  412.     if( options&DIR_UNIQ )
  413.         free_expand( av1 ), free_expand( av2 );
  414.  
  415.     return retcode;
  416. }
  417.  
  418. static int MultiCol=-1;
  419.  
  420. static void
  421. display_file( char *filestr )
  422. {
  423.     int isadir, len, collen;
  424.     char sc, *base, buf[130], *hilite;
  425.     struct file_info *info;
  426.     BPTR thislock;
  427.  
  428.     base=BaseName(filestr);
  429.     sc = *base;
  430.     *base = '\0';
  431.     thislock=Lock(filestr,SHARED_LOCK);
  432.     /* if (thislock==NULL) return; */
  433.     if( !NoTitles && (lastlock==NULL || CompareLock(thislock,lastlock))) {
  434.         /* struct InfoData *id=AllocMem( sizeof(struct InfoData), 0); */
  435.         if (col) { quickscroll(); printf("%s\n",LinePos=LineBuf); col=0; }
  436.         quickscroll();
  437.         PathName(thislock, buf, 128L);
  438.         /* Info( thislock, id ); */
  439.         if( LastWasDir )
  440.             printf(o_lolite), LastWasDir=0;
  441.         printf("Directory of %s\n", buf );
  442.         /*itok((id->id_NumBlocks-id->id_NumBlocksUsed)*id->id_BytesPerBlock));*/
  443.         /* FreeMem( id, sizeof(struct InfoData)); */
  444.         if (lastlock) UnLock(lastlock);
  445.         lastlock=thislock;
  446.     } else
  447.         UnLock(thislock);
  448.     *base    = sc;
  449.  
  450.     info   = (struct file_info *)(filestr - sizeof(struct file_info));
  451.     isadir = info->size<0;
  452.  
  453.     if( !(options & (isadir ? DIR_DIRS : DIR_FILES)))
  454.         return;
  455.  
  456.     hilite="";
  457.     if (isadir!=LastWasDir && !(options & DIR_NOCOL)) 
  458.         hilite=isadir ? o_hilite : o_lolite, LastWasDir=isadir;
  459.  
  460.     lformat(LFormat, buf, info);
  461.  
  462.     if( MultiCol==-1 ) {
  463.         quickscroll();
  464.         printf("%s%s",hilite,buf);
  465.     } else {
  466.         len=strlen(buf);
  467.         if( col+len>wwidth ) {
  468.             quickscroll();
  469.             printf("%s\n",LineBuf);
  470.             LinePos=LineBuf; col=0;
  471.         }
  472.         if( MultiCol )
  473.             colw=MultiCol;
  474.         else if( colw==-1 )
  475.             colw=len;
  476.         collen= (len+colw-1)-(len+colw-1)%colw;
  477.         col+=collen;
  478.         LinePos+=sprintf(LinePos,"%s%-*s",hilite,collen,buf);
  479.     }
  480.  
  481.     if(info->size>0)
  482.         bytes  += info->size;
  483.     blocks += info->blocks;
  484.     filecount++;
  485. }
  486.  
  487. /* will have either of these formats:
  488.  *
  489.  *    fullfilename'\0'hsparwed   <Dir>       DD-MMM-YY HH:MM:SS\n'\0'
  490.  *    fullfilename'\0'hsparwed NNNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
  491.  *                              1111111111222222222233333333334 4  4
  492.  *                    01234567890123456789012345678901234567890 1  2
  493.  */
  494.  
  495. static char linebuf[140];
  496. static long dlen, dblocks;
  497.  
  498. static void
  499. count( FIB *fib )
  500. {
  501.     dlen+=fib->fib_Size;
  502.     dblocks+=fib->fib_NumBlocks+1;
  503. }
  504.  
  505. static void
  506. lformat( char *s, char *d, struct file_info *info )
  507. {
  508.     long mi=0;
  509.     char buf[120], *w, *t, *class;
  510.     struct DPTR *dp;
  511.     int stat, i, form, sign, cut, size=info->size;
  512.     char *(*func)(int num);
  513.  
  514.     MultiCol=-1;
  515.     while( *s ) {
  516.         if( *s!='%' ) { *d++=*s++; continue; }
  517.         sign=1; form=0; cut=0; s++;
  518.         if( *s=='-' ) s++, sign=-1;
  519.         if( *s=='.' ) s++, cut=1;
  520.         while( *s>='0' && *s<='9' ) form=10*form+*s++-'0';
  521.         w=buf; w[0]=0; w[1]=0; 
  522.         switch( *s ) {
  523.         case 'p': strcpy(w,(char *)(info+1));             break;
  524.         case 'b': sprintf(w,size>=0 ? "%d":"", info->blocks); break;
  525.         case 's': sprintf(w,size>=0 ? "%d":"<Dir>",size); break;
  526.         case 'i': *w= size>=0 ? '-' : 'd';                break;
  527.         case 'r': 
  528.         case 'u':
  529.             func= *s=='r' ? itoa : itok;
  530.             strcpy( w,size>=0 ? (*func)(size) : "<Dir>");
  531.             break;
  532.         case 'n': 
  533.         case 'q':
  534.             strcpy(w,BaseName((char *)(info+1)));
  535.             if( *s=='q' && size<0 ) strcat(w,"/");
  536.             break;
  537.         case 'l':
  538.             if( info->flags & INFO_COMMENT ) *w='\n';
  539.             break;
  540.         case 'c':
  541.             *w= info->flags & INFO_COMMENT ? 'c' : '-';
  542.             break;
  543.         case 'f':
  544.             for (i=7; i>=0; i--)
  545.                 *w++ = (info->flags^15) & (1L<<i) ? "hsparwed"[7-i] : '-';
  546.             *w=0;
  547.             break;
  548.         case 'a': 
  549.             if( Stamp.ds_Days!=0 ) {
  550.                 mi =Stamp.ds_Days*1440 + Stamp.ds_Minute;
  551.                 mi-=info->date.ds_Days*1440 + info->date.ds_Minute;
  552.             }
  553.             sprintf(w,mi>=0?"%4d days %02d:%02d":"Future    ",
  554.                       mi/1440,mi/60%60,mi%60);
  555.             break;
  556.         case 'o':
  557.             if( dp=dopen( (char *)(info+1), &stat )) {
  558.                 strcpy( w, dp->fib->fib_Comment );
  559.                 dclose( dp );
  560.             }
  561.             break;
  562.         case 'v':
  563.         case 'w':
  564.             func= *s=='v' ? itoa : itok;
  565.             dlen=dblocks=0;
  566.             if( size<0 ) {
  567.                 recurse2( (char *)(info+1),count);
  568.                 strcpy( w, (*func)(dlen));
  569.                 info->size=size=dlen; info->blocks=dblocks;
  570.             } else 
  571.                 strcpy( w, (*func)(size));
  572.             break;
  573.         case 'k':
  574.             if( *info->class!=1 )
  575.                 strcpy(w,info->class);
  576.             else if( class=getclass((char *)(info+1)))
  577.                 if( w=index(strncpy(w,class,50),0xA0) )
  578.                     *w=0;
  579.             break;
  580.         case 'x':
  581.         case 'd':
  582.             sprintf(w,"%9s",dates(&info->date,*s=='x'));
  583.             if(t=index(w,' ')) *t=0;
  584.             break;
  585.         case 't': sprintf(w,"%8s", next_word(dates(&info->date,0))); break;
  586.         case 'm': MultiCol=form; form=0;      break;
  587.         case '%': *w=*++s;                    break;
  588.         case  0 : *w='%';                     break;
  589.         default : *w='%';  *w++=*s; *w=0;     break;
  590.         }
  591.         if( cut ) buf[form]=0;
  592.         *d=0; s++;
  593.         d+=sprintf(d,sign<0?"%-*s":"%*s",form,buf);
  594.     }
  595.     if( MultiCol==-1 ) { *d++='\n'; }
  596.     *d=0;
  597. }
  598.  
  599.  
  600.  
  601. int
  602. do_quit( void )
  603. {
  604.     if (Src_stack) {
  605.         Quit = 1;
  606.         return(do_return());
  607.     }
  608.     main_exit(0);
  609.     return 0;
  610. }
  611.  
  612. int
  613. do_echo( void )
  614. {
  615.     char *args=compile_av(av,1,ac,' ',0);
  616.     fprintf( (options&2)?stderr:stdout, (options&1)?"%s":"%s\n",args );
  617.     free(args);
  618.     return 0;
  619. }
  620.  
  621.  
  622. static int
  623. breakcheckd(void)
  624. {
  625.     int ret=!o_nobreak && SetSignal(0L,0L) & SIGBREAKF_CTRL_D;
  626.     if( ret )
  627.         fprintf(stderr,"^D\n");
  628.     return ret;
  629. }
  630.  
  631. /* gets a line from file, joining lines if they end in '\' */
  632.  
  633. #define MAXLINE 512
  634.  
  635. static int
  636. srcgets(char **buf, int *buflen, FILE *file)
  637. {
  638.     char *bufptr=*buf, *p, *new, concat=0, cont;
  639.     int   totlen=0;
  640.  
  641.     do {
  642.         if( totlen+MAXLINE > *buflen ) {
  643.             new=salloc(*buflen *= 2);
  644.             memcpy( new, *buf, 1+bufptr-*buf );
  645.             bufptr+= new-*buf;
  646.             free(*buf);
  647.             *buf=new;
  648.         }
  649.         if (fgets(bufptr, MAXLINE, file)==NULL) {
  650.             if( concat )
  651.                 fprintf(stderr,"Source: missing '}'\n");
  652.             else if (bufptr != *buf)
  653.                 fprintf(stderr,"Source: file ends in '\\'\n");
  654.             return -1;
  655.         }
  656.         totlen+=strlen(bufptr);
  657.  
  658.         cont=0;
  659.         
  660.         p=bufptr+strlen(bufptr)-1;
  661.         if(  p>=bufptr && *p=='\n') *p--=0;
  662.         if(  p< bufptr   ) ;
  663.         else if( *p=='\\') *p--=0, cont=1;
  664.         else if( *p=='{' ) concat++;
  665.         else if( *p=='}' ) {
  666.             if( concat>0 ) {
  667.                 concat--;
  668.                 if( concat ) *++p=';';
  669.             } else {
  670.                 fprintf(stderr,"Source: unexpected '}'\n");
  671.                 return -1;
  672.             }
  673.         } else if( concat ) *++p=';';
  674.         bufptr=++p;
  675.     } while( cont || concat );
  676.     *bufptr=0;
  677.     return totlen;
  678. }
  679.  
  680.  
  681.  
  682. int
  683. do_source( char *str )
  684. {
  685.     FILE *fi;
  686.     char *buf;
  687.     ROOT *root;
  688.     int  retcode, len, bufsize=512+MAXLINE;
  689.  
  690.     if (Src_stack == MAXSRC) {
  691.         ierror(NULL,217);
  692.         return -1;
  693.     }
  694.  
  695.     if ((fi = fopen (av[1], "r")) == 0)
  696.         { pError(av[1]); return -1;    }
  697.  
  698.     push_locals(root=(ROOT *)salloc( sizeof(ROOT)));
  699.     buf=salloc(bufsize);
  700.  
  701.     set_var(LEVEL_SET, v_passed, next_word(next_word(str)));
  702.     Src_pos  [Src_stack] = 0;
  703.     Src_abort[Src_stack] = 0;
  704.     Src_base [Src_stack] = fi;
  705.     Src_if[Src_stack]=If_stack;
  706.     ++Src_stack;
  707.     while ((len=srcgets(&buf, &bufsize, fi))>=0&& !dobreak()&& !breakcheckd()){
  708.         Src_pos[Src_stack-1] += len;
  709.         if (Verbose&VERBOSE_SOURCE && !forward_goto)
  710.             if( Verbose&VERBOSE_HILITE )
  711.                 fprintf(stderr,"%s)%s%s\n",o_hilite,buf,o_lolite);
  712.             else 
  713.                 fprintf(stderr,")%s\n",buf);
  714.         retcode=execute(buf);
  715.         if( Src_abort[Src_stack-1] ) break; else retcode=0;
  716.     }
  717.     --Src_stack;
  718.     if( If_stack>Src_if[Src_stack] )
  719.         If_stack=Src_if[Src_stack], disable=If_stack && If_base[If_stack-1];
  720.  
  721.     if (forward_goto) ierror(NULL,501);
  722.     forward_goto = 0;
  723.     unset_level(LEVEL_SOURCE + Src_stack);
  724.     unset_var(LEVEL_SET, v_gotofwd);
  725.     unset_var(LEVEL_SET, v_passed);
  726.     fclose (fi);
  727.  
  728.     pop_locals();
  729.     free(buf);
  730.     free(root);
  731.  
  732.     return retcode;
  733. }
  734.  
  735. /* set process cwd name and $_cwd, if str != NULL also print it. */
  736.  
  737. int
  738. do_pwd( char *str )
  739. {
  740.     char pwd[130];
  741.  
  742.     PathName(Myprocess->pr_CurrentDir, pwd, 128L);
  743.     if (str) puts(pwd);
  744.     set_var(LEVEL_SET, v_cwd, pwd);
  745.     /* put the current dir name in our CLI task structure */
  746.     CtoBStr(pwd, Mycli->cli_SetName, 128L);
  747.     return 0;
  748. }
  749.  
  750. /*
  751.  * CD
  752.  *
  753.  * CD(str, 0)      -do CD operation.
  754.  *
  755.  */
  756.  
  757. extern int qcd_flag;
  758.  
  759. static char lastqcd[80];
  760. static lastoffs;
  761.  
  762. int
  763. do_cd( char *str )
  764. {
  765.     BPTR oldlock, filelock;
  766.     FILE *file;
  767.     char buf[100], *old;
  768.     int  i=1, repeat;
  769.  
  770.     if( options & 1 ) {
  771.         if( !o_csh_qcd ) { fprintf(stderr,"$_qcd unset\n"); return 20; }
  772.         if( !(file=fopen( o_csh_qcd, "w" )))
  773.             { fprintf(stderr,"Can't open output\n"); return 20; }
  774.         for( ; i<ac && !breakcheck(); i++ ) {
  775.             fprintf(file,"%s\n",av[i]);
  776.             strcpy(buf,av[i]);
  777.             appendslash( buf );
  778.             expand_all( buf, file );
  779.         }
  780.         fclose(file);
  781.         return 0;
  782.     }
  783.  
  784.     str= ( has_wild && ac>=2 ) ? av[1] : next_word(str);
  785.     if (!strcmp("..",str)) str="/";
  786.  
  787.     if( !*str ) {
  788.         printf("%s\n", get_var( LEVEL_SET, v_cwd ));
  789.         return 0;
  790.     }
  791.  
  792.     if (filelock=Lock(str,ACCESS_READ)) {
  793.         lastqcd[0]=0;
  794.         if (!isdir(str)) { UnLock(filelock); ierror(str,212); return 20; }
  795.     } else {
  796.         repeat= !strncmp( lastqcd, str, 79 );
  797.         strncpy( lastqcd, str, 79);
  798.  
  799.         if( !quick_cd( buf, av[i], repeat) )
  800.             { fprintf(stderr,"Object not found %s\n",str); return 20; }
  801.         if (!(filelock=Lock(buf,ACCESS_READ))) 
  802.             { pError(buf); return 20; }
  803.     }
  804.     if (oldlock=CurrentDir(filelock)) UnLock(oldlock);
  805.     if( !(old=get_var(LEVEL_SET, v_cwd)) )
  806.         old="";
  807.     set_var(LEVEL_SET, v_lcd, old);
  808.     do_pwd(NULL);
  809.  
  810.     return 0;
  811. }
  812.  
  813. char *
  814. quick_cd( char *buf, char *name, int repeat )
  815. {
  816.     if( !o_csh_qcd )
  817.         return NULL;
  818.     qcd_flag=repeat ? 2 : 1;
  819.     strcpy(buf,name);
  820.     if( quicksearch( o_csh_qcd, 1, buf)!=2 )
  821.         return NULL;
  822.     return buf;
  823. }
  824.  
  825.  
  826. int
  827. do_mkdir( void )
  828. {
  829.     int i;
  830.     BPTR lock;
  831.     
  832.     for (i=1; i<ac; ++i) {
  833.         if (exists(av[i]))
  834.             ierror(av[i],203);
  835.         else if (lock=CreateDir(av[i]))
  836.             UnLock (lock);
  837.         else
  838.             pError(av[i]);
  839.     }
  840.     return 0;
  841. }
  842.  
  843. int
  844. do_mv( void )
  845. {
  846.     char *dest, buf[256];
  847.     int dirflag, i;
  848.  
  849.     dirflag=isdir(dest=av[--ac]);
  850.     if (ac>3 && !dirflag) { ierror(dest, 507); return (-1); }
  851.     for (i=1; i<ac; ++i) {
  852.         strcpy(buf, dest);
  853.         if (dirflag) TackOn(buf, BaseName(av[i]));
  854.         if (Rename(av[i], buf)==0)
  855.             { pError(av[i]); return -1; }
  856.         else 
  857.             clear_archive_bit( buf );
  858.     }
  859.     return 0;
  860. }
  861.  
  862. static int dirstoo;
  863.  
  864. int
  865. all_args( int (*action)(char *str), int dirsflag )
  866. {
  867.     int i;
  868.  
  869.     dirstoo=dirsflag;
  870.     for ( i=1; i<ac && !dobreak(); ++i)
  871.         if (isdir(av[i])) {
  872.             if (options & 1) recurse(av[i], action);
  873.             else if (dirstoo) (*action)(av[i]);
  874.         } else
  875.             (*action)(av[i]);
  876.     return 0;
  877. }
  878.  
  879. char *searchstring;
  880. char docr;
  881.  
  882. #define SEARCH_REC   1
  883. #define SEARCH_CASE  2
  884. #define SEARCH_WILD  4
  885. #define SEARCH_NUM   8
  886. #define SEARCH_EXCL  16
  887. #define SEARCH_QUIET 32
  888. #define SEARCH_VERB  64
  889. #define SEARCH_BIN   128
  890. #define SEARCH_FILE  256
  891. #define SEARCH_ABORT 512
  892. #define SEARCH_LEFT  1024
  893. #define SEARCH_ONLY  2048
  894.  
  895. static int abort_search;
  896. static char lowbuf[256], file_name, file_cr;
  897.  
  898. static int
  899. search_file( char *s )
  900. {
  901.     FILE *fi;
  902.     char *p, *q;
  903.     int nocasedep, lctr, len, excl=((options & 16) !=0 ), yesno;
  904.     char buf[256], searchit[120], first, left;
  905.  
  906.     if( abort_search )
  907.         return 0;
  908.  
  909.     nocasedep=!(options & SEARCH_CASE);
  910.     lctr= docr= file_name= file_cr= 0;
  911.     if (!(options & (SEARCH_QUIET|SEARCH_FILE)))
  912.         if( options & SEARCH_VERB )
  913.             printf("Examining %s...\n",s);
  914.         else 
  915.             printf("\015Examining %s...                  ",s), docr=1;
  916.  
  917.     strcpy(searchit,searchstring);
  918.     if (options & SEARCH_WILD) strcat(searchit,"\n");
  919.     len=strlen(searchit);
  920.     if (nocasedep) strupr(searchit);
  921.     first=*searchit;
  922.  
  923.     if( strcmp("STDIN",s) && !(options&SEARCH_WILD) && !excl ||
  924.                  options&SEARCH_BIN )
  925.         if( quicksearch(s,nocasedep,searchit) )
  926.             return 0;
  927.  
  928.     if( options&SEARCH_BIN )
  929.         { fprintf(stderr,"Out of memory\n"); return 20; }
  930.  
  931.     fi = strcmp("STDIN",s) ?  fopen(s,"r") : stdin;
  932.     if (fi==NULL) { pError(s); return 20; }
  933.  
  934.     prepscroll(0);
  935.  
  936.     while (fgets(buf,256,fi) && !dobreak()) {
  937.         lctr++; left=1;
  938.         if (options & SEARCH_WILD)
  939.             yesno=compare_ok(searchit, p=buf, options&SEARCH_CASE);
  940.         else {
  941.             if (nocasedep) {
  942.                 strcpy(lowbuf,buf);
  943.                 strupr(lowbuf);
  944.                 p=lowbuf;
  945.             } else
  946.                 p=buf;
  947.             q=p;
  948.             while ((p=index(p,first)) && strncmp(p++,searchit,len)) ;
  949.             yesno= (p!=NULL);
  950.             left = --p - q;
  951.         }
  952.         if( yesno ^ excl )
  953.             if(!(options&SEARCH_ONLY)|| !isalphanum(p[-1])&&!isalphanum(p[len]))
  954.                 if( found(buf, lctr, 0, s, left ) )
  955.                     break;
  956.     }
  957.     if (fi!=stdin) fclose (fi);
  958.     if( file_cr ) printf("\n");
  959.     return 0;
  960. }
  961.  
  962. int qcd_flag, qcd_offs;
  963.  
  964. static int
  965. quicksearch( char *name, int nocasedep, char *pattern )
  966. {
  967.     int i, ptrn=strlen(pattern);
  968.     char ut[256], *buffer, *lend;
  969.     char *uptab=ut, *get, c, *lpos, *lstart;
  970.     int len, lnum, qcd=qcd_flag, repeat=(qcd==2 && qcd_offs!=0);
  971.     int sofar, got;
  972.     BPTR fh;
  973.  
  974. #ifdef AZTEC_C
  975.     while(0) while(0) c=c=0, uptab=uptab=ut, get=get=NULL;
  976. #endif
  977.  
  978.     qcd_flag=0;
  979.     if( !(fh=Open(name,MODE_OLDFILE))) { 
  980.         i=(long)IoErr(), docr=0;
  981.         printf("\n");
  982.         ierror(name,i);
  983.         return 1;
  984.     }
  985.     len=filesize( name );
  986.     if( !(buffer=(void *)AllocMem(len+2,0))) { Close(fh); return 0; }
  987.     sofar=0;
  988.     do {
  989.         got=Read( fh, (char *)buffer+sofar, 60000);
  990.         sofar+=got;
  991.     } while( got==60000 );
  992.     Close( fh);
  993.     if( sofar != len ) { 
  994.         FreeMem( buffer, len+2 );
  995.         pError(pattern); return 1;
  996.     }
  997.  
  998.     if( nocasedep )
  999.         strupr( pattern );
  1000.  
  1001.     if( !qcd )
  1002.         prepscroll(0);
  1003.  
  1004.     for( i=0; i<256; i++ ) uptab[i]=i;
  1005.     if( nocasedep ) for( i='a'; i<='z'; i++ ) uptab[i]=i-'a'+'A';
  1006. retry:
  1007.     c=*pattern, buffer[len]=c, buffer[len+1]=c;
  1008.     get= (qcd==2) ? buffer+qcd_offs : buffer;
  1009.     if( qcd==1 ) qcd_offs=0;
  1010.  
  1011.     lpos=lstart=buffer, lnum=1;
  1012.     for( ;; ) {
  1013.         do ; while( uptab[*get++]!=c );
  1014.         if( --get>=buffer + len )
  1015.             break;
  1016.         for( i=1; i<ptrn; i++ )
  1017.             if( uptab[get[i]]!=pattern[i] )
  1018.                 break;
  1019.         if( i==ptrn ) {
  1020.             for( ;lpos<get; lpos++ )
  1021.                 if( *lpos=='\n' )
  1022.                     lstart=lpos+1, lnum++;
  1023.             for( lend=lstart+1; *lend!='\n'; lend++ ) ;
  1024.             if( qcd ) {
  1025.                 if( get[-1]==':' || get[-1]=='/' ||
  1026.                       lpos==lstart && lend[-1]==':' ) {
  1027.                     char *tmp;
  1028.                     for( tmp=get+ptrn; *tmp&& *tmp!='\n'&& *tmp!='/'; tmp++ );
  1029.                     if( *tmp!='/' ) {
  1030.                         *lend=0;
  1031.                         strncpy(pattern,lstart,79);
  1032.                         qcd_offs=lend-buffer;
  1033.                         FreeMem( buffer, len+2 );
  1034.                         return 2;
  1035.                     }
  1036.                 } else 
  1037.                     lend=lpos+1;
  1038.             } else {
  1039.                 *lend=0;
  1040.                 if(!(options&SEARCH_ONLY) ||
  1041.                      !isalphanum(lpos[-1])&&!isalphanum(lpos[ptrn]))
  1042.                     if(found(lstart, lnum, get-buffer, name, lpos==lstart ))
  1043.                         break;
  1044.                 *lend='\n';
  1045.             }
  1046.             get=lend+1;
  1047.         } else
  1048.             get++;
  1049.     }
  1050.     if( repeat )  { repeat=0; qcd_offs=0; goto retry; }
  1051.     if( file_cr ) { printf("\n"); quickscroll(); }
  1052.     FreeMem( buffer, len+2 );
  1053.     return 1;
  1054. }
  1055.  
  1056. static int
  1057. found( char *lstart, int lnum, int loffs, char *name, char left )
  1058. {
  1059.     int fileabort=0;
  1060.  
  1061.     if( (options&SEARCH_LEFT) && !left)
  1062.         return 0;
  1063.  
  1064.     if ( docr )
  1065.         { quickscroll(); printf("\n"); docr=0; }
  1066.  
  1067.     if( options&SEARCH_FILE ) {
  1068.         file_cr=1;
  1069.         if( !file_name )
  1070.             printf("%s",name), file_name=1;
  1071.         if( options&SEARCH_NUM )
  1072.             fileabort=1;
  1073.         else 
  1074.             printf(" %d",lnum);
  1075.     } else if( options & SEARCH_BIN ) {
  1076.         if (!(options & SEARCH_NUM))
  1077.             printf("Byte offset %d\n",loffs);
  1078.         else 
  1079.             printf("%d\n",loffs);
  1080.         quickscroll();
  1081.     } else {
  1082.         if (!(options & SEARCH_NUM))
  1083.             printf("%4d ",lnum);
  1084.         printf((lstart[strlen(lstart)-1]=='\n')?"%s":"%s\n",lstart);
  1085.         quickscroll();
  1086.     }
  1087.     abort_search= options&SEARCH_ABORT;
  1088.     return dobreak() || fileabort || abort_search;
  1089. }
  1090.  
  1091.  
  1092. int
  1093. do_search( void )
  1094. {
  1095.     if(!isconsole(Output())) options |= SEARCH_VERB;
  1096.     abort_search=0;
  1097.     searchstring=av[--ac];
  1098.     all_args(search_file, 0);
  1099.     if(docr) printf("\n"),docr=0;
  1100.     return 0;
  1101. }
  1102.  
  1103. static int
  1104. rm_file(char *file)
  1105. {
  1106.     if ( file[strlen(file)-1]=='/' ) file[strlen(file)-1]=0;
  1107.     if (has_wild) printf(" %s...",file);
  1108.     if (options & 2) SetProtection(file,0L);
  1109.     if (!DeleteFile(file)) {
  1110.         if( !(options & 4) )
  1111.             { pError (file); return 20; }
  1112.     } else if (has_wild)
  1113.         printf("Deleted\n");
  1114.     return 0;
  1115. }
  1116.  
  1117. int
  1118. do_rm( void )
  1119. {
  1120.     all_args( rm_file, 1);
  1121.     return 0;
  1122. }
  1123.  
  1124. char *NameCopy;
  1125. int (*Action)(char *);
  1126. int Level;
  1127.  
  1128. static void
  1129. true_recurse( char *name )
  1130. {
  1131.     BPTR lock, cwd;
  1132.     FIB *fib=(FIB *)SAllocMem((long)sizeof(FIB),MEMF_PUBLIC);
  1133.  
  1134.     NameCopy[0]=0;
  1135.     if (lock=Lock(name,ACCESS_READ)) {
  1136.         cwd =CurrentDir(lock);
  1137.         if (Examine(lock, fib))
  1138.             while (ExNext(lock, fib) && !CHECKBREAK()) {
  1139.                 if (*NameCopy) { (*Action)(NameCopy); NameCopy[0]=0; }
  1140.                 if (fib->fib_DirEntryType==ST_USERDIR) {
  1141.                     true_recurse(fib->fib_FileName);
  1142.                     if (dirstoo) { strcpy(NameCopy,fib->fib_FileName); }
  1143.                 } else if( fib->fib_DirEntryType<0 )
  1144.                     strcpy(NameCopy,fib->fib_FileName);
  1145.             }
  1146.         if (*NameCopy) { (*Action)(NameCopy); NameCopy[0]=0; }
  1147.  
  1148.         UnLock(CurrentDir(cwd));
  1149.     } else
  1150.         pError(name);
  1151.     FreeMem(fib, (long)sizeof(FIB));
  1152. }
  1153.  
  1154. static void
  1155. recurse(char *name, int (*action)(char *))
  1156. {
  1157.     NameCopy=salloc(256);
  1158.     Action=action;
  1159.     true_recurse( name );
  1160.     if (dirstoo) { (*Action)(name); }
  1161.     free(NameCopy);
  1162. }
  1163.  
  1164.  
  1165. static void
  1166. recurse2( char *name, void (*action)(FIB *))
  1167. {
  1168.     BPTR lock, cwd;
  1169.     FIB  *fib=(FIB *)SAllocMem(sizeof(FIB),MEMF_PUBLIC);
  1170.  
  1171.     if (lock=Lock(name,ACCESS_READ)) {
  1172.         cwd =CurrentDir(lock);
  1173.         if (Examine(lock, fib))
  1174.             while (ExNext(lock, fib) && !CHECKBREAK()) {
  1175.                 (*action)(fib);
  1176.                 if (fib->fib_DirEntryType==ST_USERDIR)
  1177.                     recurse2(fib->fib_FileName,action);
  1178.             }
  1179.         UnLock(CurrentDir(cwd));
  1180.     }
  1181.  
  1182.     FreeMem(fib, sizeof(FIB));
  1183. }
  1184.  
  1185.  
  1186. int
  1187. do_history( void )
  1188. {
  1189.     struct HIST *hist;
  1190.     int i = H_tail_base;
  1191.     int len = (av[1]) ? strlen(av[1]) : 0;
  1192.  
  1193.     for (hist = H_tail; hist && !dobreak(); hist = hist->prev, i++)
  1194.         if (len == 0 || !strncmp(av[1], hist->line, len))
  1195.             printf("%3d %s\n", i, hist->line);
  1196.     return 0;
  1197. }
  1198.  
  1199. int
  1200. do_mem( void )
  1201. {
  1202.     static long clast, flast;
  1203.     long cfree, ffree, i;
  1204.     char *desc="Free", *mem;
  1205.  
  1206.     if( options&32 )
  1207.         for( i=0; i<4; i++ )
  1208.             if(mem=AllocMem(0x7fffffff,0))
  1209.                 FreeMem(mem,0x7fffffff);
  1210.  
  1211.     Forbid();
  1212.     cfree = AvailMem (MEMF_CHIP);
  1213.     ffree = AvailMem (MEMF_FAST);
  1214.     Permit();
  1215.     if( options&8 ) {
  1216.         clast=cfree, flast=ffree;
  1217.         return 0;
  1218.     }
  1219.     if( options&16 )
  1220.         cfree=clast-cfree, ffree=flast-ffree, desc="Used";
  1221.     if( options&4 ) {
  1222.         if     ( options & 1 ) printf("%ld\n",cfree);
  1223.         else if( options & 2 ) printf("%ld\n",ffree);
  1224.         else                   printf("%ld\n",cfree+ffree);
  1225.     } else {
  1226.         if     ( options & 1 ) printf("Free CHIP memory:%10s\n",itoa(cfree));
  1227.         else if( options & 2 ) printf("Free FAST memory:%10s\n",itoa(ffree));
  1228.         else {
  1229.             if(ffree) {
  1230.                 printf("FAST memory:%10s\n",itoa(ffree));
  1231.                 printf("CHIP memory:%10s\n",itoa(cfree));
  1232.             }
  1233.             printf("Total  %s:%10s\n",desc,itoa(cfree+ffree));
  1234.         }
  1235.     }
  1236.     return 0;
  1237. }
  1238.  
  1239. int
  1240. do_forline( void )
  1241. {
  1242.     char vname[33], buf[256], *cstr;
  1243.     int lctr;
  1244.     FILE *f;
  1245.  
  1246.     strcpy(vname,av[1]);
  1247.     if( !strcmp(av[2],"STDIN") )
  1248.         f=stdin;
  1249.     else 
  1250.         if(!(f=fopen(av[2],"r"))) { pError(av[2]); return 20; }
  1251.  
  1252.     lctr=0;
  1253.     ++H_stack;
  1254.     cstr = compile_av (av, 3, ac, ' ', 0);
  1255.     while (fgets(buf,256,f) && !dobreak() && !breakcheckd()) {
  1256.         buf[strlen(buf)-1]='\0';    /* remove CR */
  1257.         lctr++;
  1258.         set_var(LEVEL_SET, vname, buf);
  1259.         sprintf(buf,"%d",lctr);
  1260.         set_var(LEVEL_SET, v_linenum, buf);
  1261.         exec_command(cstr);
  1262.     }
  1263.     if( f!=stdin ) fclose(f);
  1264.     --H_stack;
  1265.     free (cstr);
  1266.     unset_var (LEVEL_SET, vname);
  1267.     unset_var (LEVEL_SET, v_linenum);
  1268.     return 0;
  1269. }
  1270.  
  1271. int
  1272. do_fornum( void )
  1273. {
  1274.     char vname[33], buf[16];
  1275.     int n1, n2, step, i=1, verbose;
  1276.     char *cstr;
  1277.  
  1278.     verbose=(options & 1);
  1279.     strcpy(vname,av[i++]);
  1280.     n1=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
  1281.     n2=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
  1282.     if (options & 2) {
  1283.         step=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
  1284.     } else
  1285.         step=1;
  1286.     ++H_stack;
  1287.     cstr = compile_av (av, i, ac, ' ', 0);
  1288.     for (i=n1; (step>=0 ? i<=n2 : i>=n2) && !CHECKBREAK() && !breakcheckd();
  1289.          i+=step) {
  1290.         if (verbose) fprintf(stderr, "fornum: %d\n", i);
  1291.         sprintf(buf,"%d",i);
  1292.         set_var (LEVEL_SET, vname, buf);
  1293.         exec_command(cstr);
  1294.     }
  1295.     --H_stack;
  1296.     free (cstr);
  1297.     unset_var (LEVEL_SET, vname);
  1298.     return 0;
  1299. }
  1300.  
  1301. /*
  1302.  * foreach var_name  ( str str str str... str ) commands
  1303.  * spacing is important (unfortunately)
  1304.  *
  1305.  * ac=0    1 2 3 4 5 6 7
  1306.  * foreach i ( a b c ) echo $i
  1307.  * foreach i ( *.c ) "echo -n "file ->";echo $i"
  1308.  */
  1309.  
  1310. int
  1311. do_foreach( void )
  1312. {
  1313.     int cstart, cend;
  1314.     char *cstr, vname[33];
  1315.     char **fav;
  1316.     int i=1, verbose;
  1317.  
  1318.     verbose=(options & 1);
  1319.     strcpy(vname, av[i++]);
  1320.     if (*av[i] == '(') i++;
  1321.     cstart = i;
  1322.     while (i<ac && *av[i] != ')') i++;
  1323.     if (i > ac) { fprintf(stderr,"')' expected\n"); return 20; }
  1324.     ++H_stack;
  1325.     cend = i;
  1326.  
  1327.     fav = (char **)salloc(sizeof(char *) * (ac));
  1328.     for (i = cstart; i < cend; ++i) fav[i] = av[i];
  1329.  
  1330.     cstr = compile_av (av, cend + 1, ac, ' ', 0);
  1331.  
  1332.     for (i = cstart; i<cend && !CHECKBREAK() && !breakcheckd(); ++i) {
  1333.         set_var (LEVEL_SET, vname, fav[i]);
  1334.         if (verbose) fprintf(stderr, "foreach: %s\n", fav[i]);
  1335.         execute(cstr);
  1336.     }
  1337.     --H_stack;
  1338.     free (fav);
  1339.     free (cstr);
  1340.     unset_var (LEVEL_SET, vname);
  1341.     return 0;
  1342. }
  1343.  
  1344. int
  1345. do_forever( char *str )
  1346. {
  1347.     int rcode = 0;
  1348.     char *ptr = next_word( str );
  1349.  
  1350.     ++H_stack;
  1351.     for (;;) {
  1352.         if (CHECKBREAK() || breakcheckd()) { rcode = 20; break; }
  1353.         if (exec_command (ptr) < 0) {
  1354.             str = get_var(LEVEL_SET, v_lasterr);
  1355.             rcode = (str) ? atoi(str) : 20;
  1356.             break;
  1357.         }
  1358.     }
  1359.     --H_stack;
  1360.     return rcode;
  1361. }
  1362.  
  1363. extern struct IntuitionBase *IntuitionBase;
  1364.  
  1365. int
  1366. do_window( void )
  1367. {
  1368.     long x=-1, y=-1, w=-1, h=-1, maxwidth, maxheight, arg[5];
  1369.     int i;
  1370.  
  1371.     if(options & 32) {
  1372.         struct Screen *scrn;
  1373.         struct Window *window;
  1374.         char buf[80];
  1375.         buf[40]=0;
  1376.         for (scrn=IntuitionBase->FirstScreen; scrn; scrn=scrn->NextScreen) {
  1377.             buf[0]=0;
  1378.             if( scrn->Title )
  1379.                 strncpy(buf,(char*)scrn->Title,40);
  1380.             printf("\nScreen \"%s\" (%d,%d,%dx%d):\n",
  1381.                 buf,
  1382.                 scrn->LeftEdge,
  1383.                 scrn->TopEdge,
  1384.                 scrn->Width,
  1385.                 scrn->Height
  1386.             );
  1387.             for (window=scrn->FirstWindow; window; window=window->NextWindow) {
  1388.                 buf[0]=0;
  1389.                 if( window->Title )
  1390.                     strncpy(buf,(char*)window->Title,40);
  1391.                 printf("\tWindow\t\"%s\" (%d,%d,%dx%d)\n",
  1392.                     buf,
  1393.                     window->LeftEdge,
  1394.                     window->TopEdge,
  1395.                     window->Width,
  1396.                     window->Height
  1397.                 );
  1398.             }
  1399.         }
  1400.         return 0;
  1401.     }
  1402.  
  1403.     if( o_nowindow || !Win )
  1404.         return 20;
  1405.  
  1406.     maxwidth = Win->WScreen->Width;
  1407.     maxheight= Win->WScreen->Height;
  1408.     if( options&1 )
  1409.         x=Win->LeftEdge,y=Win->TopEdge,w=Win->MinWidth,h=Win->MinHeight;
  1410.     if( options&2 ) x=y=0, w=maxwidth, h=maxheight;
  1411.     if( options&4 ) WindowToFront(Win);
  1412.     if( options&8 ) WindowToBack(Win);
  1413.     if( options&16) ActivateWindow(Win);
  1414.     if( ac >= 5) {
  1415.         for(i=1; i<5; i++) {
  1416.             arg[i] = myatoi(av[i],0,1023); if (atoierr) return 20;
  1417.         }
  1418.         x=arg[1]; y=arg[2]; w=arg[3]; h=arg[4];
  1419.     }
  1420.     if( w!=-1 ) {
  1421.         int i;
  1422.         if ( x+w>maxwidth || y+h>maxheight ) {
  1423.             ierror(NULL, 500);
  1424.             return 20;
  1425.         }
  1426.         if( w<Win->MinWidth  ) w=Win->MinWidth;
  1427.         if( h<Win->MinHeight ) h=Win->MinHeight;
  1428.         if( Win->LeftEdge!=0 || Win->TopEdge!=0 )
  1429.             MoveWindow(Win, -Win->LeftEdge, -Win->TopEdge );
  1430.         if( Win->Width!=w || Win->Height!=h )
  1431.             SizeWindow(Win, w-Win->Width   , h-Win->Height  );
  1432.         if( x || y )
  1433.             MoveWindow(Win, x, y );
  1434.         for( i=0; i<10; i++ ) {
  1435.             if(  Win->LeftEdge==x && Win->TopEdge==y && 
  1436.                  Win->Width   ==w && Win->Height ==h )
  1437.                 break;
  1438.             Delay(5);
  1439.         }
  1440.     } else 
  1441.         Delay(20); /* pause 1/2 sec. before trying to print */
  1442.  
  1443.     Delay(10);
  1444.     printf("\014");
  1445.     return 0;
  1446. }
  1447.  
  1448.  
  1449. static void
  1450. setsystemtime(struct DateStamp *ds)
  1451. {
  1452.     struct timerequest tr;
  1453.     long secs= ds->ds_Days*86400+ds->ds_Minute*60+ds->ds_Tick/TICKS_PER_SECOND;
  1454.  
  1455.     if (OpenDevice(TIMERNAME, UNIT_VBLANK,(struct IORequest *)&tr, 0L)) {
  1456.         fprintf(stderr,"Clock error: can't open timer device\n");
  1457.         return;
  1458.     }
  1459.  
  1460.     tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  1461.     tr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
  1462.     tr.tr_node.io_Message.mn_Node.ln_Name = NULL;
  1463.     tr.tr_node.io_Message.mn_ReplyPort = NULL;
  1464.     tr.tr_node.io_Command = TR_SETSYSTIME;
  1465.     tr.tr_time.tv_secs = secs;
  1466.     tr.tr_time.tv_micro = 0L;
  1467.     if (DoIO ((struct IORequest *)&tr))
  1468.         fprintf(stderr,"Clock error: can't talk to timer device\n");
  1469.     CloseDevice ((struct IORequest *)&tr);
  1470. }
  1471.  
  1472. static char tday[10];
  1473.  
  1474. char *
  1475. dates( struct DateStamp *dss, int flags )
  1476. {
  1477.     static char timestr[40];
  1478.     char tdate[10], ttime[10];
  1479.     struct DateTime dt;
  1480.     struct DateStamp *myds=&(dt.dat_Stamp);
  1481.  
  1482.     dt.dat_Format=FORMAT_DOS;
  1483.     dt.dat_StrDay=tday;
  1484.     dt.dat_StrDate=tdate;
  1485.     dt.dat_StrTime=ttime;
  1486.     dt.dat_Flags=flags ? DTF_SUBST : 0;
  1487.     myds->ds_Days=dss->ds_Days;
  1488.     myds->ds_Minute=dss->ds_Minute;
  1489.     myds->ds_Tick=dss->ds_Tick;
  1490.     if(  myds->ds_Days<0   || myds->ds_Days>36500 ||
  1491.          myds->ds_Minute<0 || myds->ds_Minute>1440 || 
  1492.          myds->ds_Tick<0   || myds->ds_Tick>3000 || StamptoStr(&dt) )
  1493.         strcpy(tdate,"---------"), strcpy(ttime,"--------");
  1494.     ttime[8]=0;
  1495.     sprintf(timestr,"%-9s %-8s",tdate,ttime);
  1496.     timestr[18]=0;    /* protection against bad timestamped files */
  1497.     return timestr;
  1498. }
  1499.  
  1500. int
  1501. do_date( void )
  1502. {
  1503.     static long stopwatch;
  1504.     struct DateStamp dss;
  1505.     struct DateTime dt;
  1506.     long time;
  1507.     int i=1;
  1508.  
  1509.     dt.dat_Format=FORMAT_DOS;
  1510.     if (ac==1) {
  1511.         DateStamp(&dss);
  1512.         time=dss.ds_Minute*6000+2*dss.ds_Tick;   /* 2 = 100/TickPerSec   */
  1513.         if( options & 1 )
  1514.             stopwatch=time;
  1515.         else if( options&2 )
  1516.             printf( "%d.%02d\n",(time-stopwatch)/100,(time-stopwatch)%100);
  1517.         else 
  1518.             printf("%s %s\n",tday,dates(&dss,0));
  1519.     } else {
  1520.         DateStamp(&dt.dat_Stamp);
  1521.         for ( ; i<ac; i++) {
  1522.             dt.dat_StrDate=NULL;
  1523.             dt.dat_StrTime=NULL;
  1524.             dt.dat_Flags=DTF_FUTURE;
  1525.             if (index(av[i],':')) dt.dat_StrTime=av[i];
  1526.                 else dt.dat_StrDate=av[i];
  1527.             if (StrtoStamp(&dt)) ierror(av[i],500);
  1528.         }
  1529.         setsystemtime( & (dt.dat_Stamp) );
  1530.     }
  1531.     return 0;
  1532. }
  1533.